 /*
  * Copyright (C) 2005 db4objects Inc. http://www.db4o.com
  *
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
  * db4objects - Initial API and implementation
  */
 package org.eclipse.core.internal.databinding.conversion;

 import java.text.ParsePosition ;
 import java.util.Date ;

 import org.eclipse.core.internal.databinding.BindingMessages;

 import com.ibm.icu.text.DateFormat;
 import com.ibm.icu.text.SimpleDateFormat;

 /**
  * Base support for date/string conversion handling according to the default
  * locale or in plain long milliseconds.
  * <p>
  * NOTE: parse(format(date)) will generally *not* be equal to date, since the
  * string representation may not cover the sub-second range, time-only string
  * representations will be counted from the beginning of the era, etc.
  * </p>
  */
 public abstract class DateConversionSupport {
     private final static int DATE_FORMAT=DateFormat.SHORT;
     private final static int DEFAULT_FORMATTER_INDEX=0;

     private final static int NUM_VIRTUAL_FORMATTERS=1;
     
     /**
      * Alternative formatters for date, time and date/time.
      * Raw milliseconds are covered as a special case.
      */
     // TODO: These could be shared, but would have to be synchronized.
 private DateFormat[] formatters = {
             new SimpleDateFormat(BindingMessages.getString("DateFormat_DateTime")), //$NON-NLS-1$
 new SimpleDateFormat(BindingMessages.getString("DateFormat_Time")), //$NON-NLS-1$
 DateFormat.getDateTimeInstance(DATE_FORMAT, DateFormat.SHORT),
             DateFormat.getDateInstance(DATE_FORMAT),
             DateFormat.getTimeInstance(DateFormat.SHORT),
             DateFormat.getDateTimeInstance(DATE_FORMAT,DateFormat.MEDIUM),
             DateFormat.getTimeInstance(DateFormat.MEDIUM)
     };
     
     /**
      * Tries all available formatters to parse the given string according to the
      * default locale or as a raw millisecond value and returns the result of the
      * first successful run.
      *
      * @param str A string specifying a date according to the default locale or in raw milliseconds
      * @return The parsed date, or null, if no available formatter could interpret the input string
      */
     protected Date parse(String str) {
         for (int formatterIdx = 0; formatterIdx < formatters.length; formatterIdx++) {
             Date parsed=parse(str,formatterIdx);
             if(parsed!=null) {
                 return parsed;
             }
         }
         return null;
     }

     protected Date parse(String str,int formatterIdx) {
         if(formatterIdx>=0) {
                 ParsePosition pos=new ParsePosition (0);
                 if (str == null) {
                     return null;
                 }
                 Date date=formatters[formatterIdx].parse(str,pos);
                 if(pos.getErrorIndex()!=-1||pos.getIndex()!=str.length()) {
                     return null;
                 }
                 return date;
         }
         try {
             long millisecs=Long.parseLong(str);
             return new Date (millisecs);
         }
         catch(NumberFormatException exc) {
         }
         return null;
     }
     
     /**
      * Formats the given date with the default formatter according to the default locale.
      * @param date a date
      * @return a string representation of the given date according to the default locale
      */
     protected String format(Date date) {
         return format(date,DEFAULT_FORMATTER_INDEX);
     }

     protected String format(Date date,int formatterIdx) {
         if(formatterIdx>=0) {
             return formatters[formatterIdx].format(date);
         }
         return String.valueOf(date.getTime());
     }

     protected int numFormatters() {
         return formatters.length+NUM_VIRTUAL_FORMATTERS;
     }
     
     /**
      * Returns the date format for the provided <code>index</code>.
      * <p>
      * This is for testing purposes only and should not be a part of the API if
      * this class was to be exposed.
      * </p>
      *
      * @param index
      * @return date format
      */
     protected DateFormat getDateFormat(int index) {
         if (index < 0 || index >= formatters.length) {
             throw new IllegalArgumentException ("'index' [" + index + "] is out of bounds."); //$NON-NLS-1$//$NON-NLS-2$
 }
         
         return formatters[index];
     }
 }
